
#include <stdio.h>
#include "vertex_buffer_object_gl15.h"

VertexBufferObjectGL15::VertexBufferObjectGL15 (bool isIndex, GLMMDATATYPE type)
  : name (0)
  , type(type)
{
    target = isIndex ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
    
}

VertexBufferObjectGL15::~VertexBufferObjectGL15 ()
{

}

GLMMRESULT VertexBufferObjectGL15::PrepareData (unsigned size, GLMMUSAGE usage)
{
    GLenum glusage;
    switch (usage)
    {
        case GLMMUSAGE_DYNMIC:
            glusage = GL_DYNAMIC_DRAW;
            break;
        case GLMMUSAGE_STATIC:
            glusage = GL_STATIC_DRAW;
            break;
        case GLMMUSAGE_STREAM:
            glusage = GL_STREAM_DRAW;
            break;
        default:
            return GLMM_ERROR_INVALIDOPERATOR;
    }

    if (name)
      {
        return GLMM_ERROR_ALREADYINITIALIZED;
      }

    glGenBuffers (1, &name);
    if (!name)
      {
        return GLMM_ERROR_OUTOFMEMORY;
      }


    glBindBuffer (target, name);
    glBufferData (target, size, NULL, glusage);

    return GLMM_OK;
}

GLMMRESULT VertexBufferObjectGL15::Lock (GLMMLOCK lock, void** data)
{
    GLenum access;
    switch (lock)
    {
        case GLMMLOCK_READ:
          access = GL_READ_ONLY;
          break;
        case GLMMLOCK_WRITE:
          access = GL_WRITE_ONLY;
          break;
        case GLMMLOCK_READWRITE:
          access = GL_READ_WRITE;
          break;
        default:
          return GLMM_ERROR_INVALIDOPERATOR;
    }
    
    if (!name)
      {
        return GLMM_ERROR_NOTINITIALIZED;
      }
    
    if (!data)
      {
        return GLMM_ERROR_NULLOBJECT;
      }
    
    glBindBuffer (target, name);
    *data = glMapBuffer (target, access);
    
    if (!*data)
      {
        return GLMM_ERROR_NULLOBJECT;
      }
    
    return GLMM_OK;
}

GLMMRESULT VertexBufferObjectGL15::Unlock ()
{
    if (!name)
      {
        return GLMM_ERROR_NOTINITIALIZED;
      }
    
    glUnmapBuffer (target);
    return GLMM_OK;
}

int VertexBufferObjectGL15::GetName () const
{
    return name;
}

int VertexBufferObjectGL15::GetType () const
{
    return target;
}

GLMMRESULT VertexBufferObjectGL15::Bind ()
{
    if (!target || !name)
      {
        return GLMM_ERROR_NOTINITIALIZED;
      }
 
    glBindBuffer (target, name);
    return GLMM_OK;
}


GLMMDATATYPE VertexBufferObjectGL15::GetDataType () const
{
    return type;
}